define(function (require) {
	/**
     * 构造函数
     *
     * @param {leaflet} map
     * @param {echarts} ec
     * @constructor
     */
	function LeafletMapExt(map, ec) {
		this._init(map, ec);
	};
	//includes: [L.Mixin.Events],
	LeafletMapExt.prototype._echartsContainer = null;
	LeafletMapExt.prototype._map = null;
	LeafletMapExt.prototype._ec = null;
	LeafletMapExt.prototype._option = null;
	LeafletMapExt.prototype._geoCoord = [];
	LeafletMapExt.prototype._mapOffset = [0, 0];
	LeafletMapExt.prototype._delta = 0;
	LeafletMapExt.prototype._startTime = null;
	LeafletMapExt.prototype._lastMousePos = null;
	LeafletMapExt.prototype._bshow = false;
	LeafletMapExt.prototype._vid = false;

	LeafletMapExt.prototype._init = function (map, ec) {
		var self = this;
		self._map = map;
		
		//初始化mapoverlay
		var size = map.getSize();
		var div = this._echartsContainer = document.createElement('div');
		div.id = "leaflet-map-ec-ext";
		div.style.position = 'absolute';
		div.style.height = size.y + 'px';
		div.style.width = size.x + 'px';
		div.style.top = 0;
		div.style.left = 0;
		div.style.zIndex = 300;
		map.getPanes().overlayPane.appendChild(div);
		this._bshow = true;
		
		/**
		 * 获取echarts容器
		 *
		 * @return {HTMLElement}
		 * @public
		 */
		self.getEchartsContainer = function () {
			return self._echartsContainer;
		};
		
		self.fadeOut = function(speed, callback) {
			$("#leaflet-map-ec-ext").fadeOut(speed,callback);
		};
		
		self.fadeIn = function(speed, callback) {
			$("#leaflet-map-ec-ext").fadeIn(speed,callback);
		};
		
		self.hide = function () {
			$("#leaflet-map-ec-ext").hide();
		};
		
		self.show = function () {
			$("#leaflet-map-ec-ext").show();
		};

		self.clear = function () {
			if (self._ec) self._ec.clear();
		};
		
		self.dispose = function () {
			if (self._ec) {
				//self._unbindEvent();
				self._ec.dispose();
				self._ec = null;
			}
		};

		self.remove = function () {
			if (self._bshow) {
				self._map.getPanes().overlayPane.removeChild(self._echartsContainer);
				self._bshow = false;
			}
		};
		
		self.add = function () {
			if (!self._bshow) {
				var size = self._map.getSize();
				var div = this._echartsContainer;
				div.style.position = 'absolute';
				div.style.height = size.y + 'px';
				div.style.width = size.x + 'px';
				div.style.top = 0;
				div.style.left = 0;
				self._map.getPanes().overlayPane.appendChild(div);
			}
			self._bshow = true;
		};
		
		/**
		 * 获取map实例
		 *
		 * @return {map.Map}
		 * @public
		 */
		self.getMap = function () {
			return self._map;
		};
		/**
		 * 经纬度转换为屏幕像素
		 *
		 * @param {Array.<number>} geoCoord  经纬度
		 * @return {Array.<number>}
		 * @public
		 */
		self.geoCoord2Pixel = function (geoCoord) {
			var point = new L.latLng(geoCoord[1], geoCoord[0]);
			var pos = self._map.latLngToContainerPoint(point);
			return [pos.x, pos.y];
		};

		/**
		 * 屏幕像素转换为经纬度
		 *
		 * @param {Array.<number>} pixel  像素坐标
		 * @return {Array.<number>}
		 * @public
		 */
		self.pixel2GeoCoord = function (pixel) {
			var point = self._map.containerPointToLatLng(L.point(pixel[0], pixel[1]));
			return [point.lng, point.lat];
		};

		/**
		 * 初始化echarts实例
		 *
		 * @return {ECharts}
		 * @public
		 */
		self.initECharts = function () {
			self._ec = ec.init.apply(self, arguments);
			self._bindEvent();
			self._addMarkWrap();
			return self._ec;
		};

		// addMark wrap for get position from baidu map by geo location
		// by kener at 2015.01.08
		self._addMarkWrap = function () {
			function _addMark(seriesIdx, markData, markType) {
				var data;
				if (markType == 'markPoint') {
					var data = markData.data;
					if (data && data.length) {
						for (var k = 0, len = data.length; k < len; k++) {
							if (!(data[k].name && this._geoCoord.hasOwnProperty(data[k].name))) {
								data[k].name = k + 'markp';
								self._geoCoord[data[k].name] = data[k].geoCoord;
							}
							self._AddPos(data[k]);
						}
					}
				} else {
					data = markData.data;
					if (data && data.length) {
						for (var k = 0, len = data.length; k < len; k++) {
							if (!(data[k][0].name && this._geoCoord.hasOwnProperty(data[k][0].name))) {
								data[k][0].name = k + 'startp';
								self._geoCoord[data[k][0].name] = data[k][0].geoCoord;
							}
							if (!(data[k][1].name && this._geoCoord.hasOwnProperty(data[k][1].name))) {
								data[k][1].name = k + 'endp';
								self._geoCoord[data[k][1].name] = data[k][1].geoCoord;
							}
							self._AddPos(data[k][0]);
							self._AddPos(data[k][1]);
						}
					}
				}
				self._ec._addMarkOri(seriesIdx, markData, markType);
			}

			self._ec._addMarkOri = self._ec._addMark;
			self._ec._addMark = _addMark;
		};

		/**
		 * 获取ECharts实例
		 *
		 * @return {ECharts}
		 * @public
		 */
		self.getECharts = function () {
			return self._ec;
		};

		/**
		 * 获取地图的偏移量
		 *
		 * @return {Array.<number>}
		 * @public
		 */
		self.getMapOffset = function () {
			return self._mapOffset;
		};

		/**
		 * 对echarts的setOption加一次处理
		 * 用来为markPoint、markLine中添加x、y坐标，需要name与geoCoord对应
		 *
		 * @public
		 * @param option
		 * @param notMerge
		 */
		self.setOption = function (option, notMerge) {
			if (!self._ec) return;
			if(option===null) return;
			self._option = option;
			var series = option.series || {};
			
			//重新确定面板位置
			var domPosition = self._map._getMapPanePos();
			// 记录偏移量
			self._mapOffset = [-parseInt(domPosition.x) || 0, -parseInt(domPosition.y) || 0];
			self._echartsContainer.style.left = self._mapOffset[0] + 'px';
			self._echartsContainer.style.top = self._mapOffset[1] + 'px';

			// 记录所有的geoCoord
			for (var i = 0, item; item = series[i++]; ) {
				if (item.type == "map") {
						var geoCoord = item.geoCoord;
						var data = item.data;
						if (geoCoord) {
							for (var k in geoCoord) {
								self._geoCoord[k] = geoCoord[k];
							}
						}
					} else {
						var geoCoord = item.geoCoord;
						var center = item.center;
						if (geoCoord) {
							//console.log("coord: " + geoCoord[0] + ", " + geoCoord[1]);
							var pos = self.geoCoord2Pixel(geoCoord);
							center[0] = pos[0];// - self._mapOffset[0];
							center[1] = pos[1];// - self._mapOffset[1];
							//console.log("center: " + center[0] + ", " + center[1]);
						}
					}
					/*
          var geoCoord = item.geoCoord;
          if (geoCoord) {
            for (var k in geoCoord) {
              self._geoCoord[k] = geoCoord[k];
            }
          }*/
         		if (item.type == "pie") {
         			var pradius = item.pradius;
         			var radius = item.radius;
         			var piesize = maplevel4size[0];
					var sizeScale = maplevel4size[1];
					var zoom = parseInt(map.getZoom());//触摸屏缩放时，zoom非整数
					if(zoom > maplevel4size.length || zoom===maplevel4size.length) zoom = maplevel4size.length;
					piesize = maplevel4size[zoom];
					if(isArray(radius)) {
         				item.radius[1] = radius[1] - pradius + piesize;
         				if(item.radius[0]!=0) item.radius[0] = item.radius[1] * 0.5;
         			} else {
         				item.radius = radius - pradius + piesize;
         			}
         			item.pradius = piesize;
         		}
			}

			// 添加x、y
			for (var i = 0, item; item = series[i++]; ) {
				var markPoint = item.markPoint || {};
				var markLine = item.markLine || {};

				var data = markPoint.data;
				if (data && data.length) {
					for (var k = 0, len = data.length; k < len; k++) {
						if (!(data[k].name && this._geoCoord.hasOwnProperty(data[k].name))) {
							data[k].name = k + 'markp';
							self._geoCoord[data[k].name] = data[k].geoCoord;
						}
						self._AddPos(data[k]);
					}
				}

				data = markLine.data;
				if (data && data.length) {
					for (var k = 0, len = data.length; k < len; k++) {
						if (!(data[k][0].name && this._geoCoord.hasOwnProperty(data[k][0].name))) {
							data[k][0].name = k + 'startp';
							self._geoCoord[data[k][0].name] = data[k][0].geoCoord;
						}
						if (!(data[k][1].name && this._geoCoord.hasOwnProperty(data[k][1].name))) {
							data[k][1].name = k + 'endp';
							self._geoCoord[data[k][1].name] = data[k][1].geoCoord;
						}
						self._AddPos(data[k][0]);
						self._AddPos(data[k][1]);
					}
				}
			}
			self._ec.setOption(option, notMerge);
		};

		/**
		 * 增加x、y坐标
		 *
		 * @param {Object} obj  markPoint、markLine data中的项，必须有name
		 * @param {Object} geoCoord
		 */
		self._AddPos = function (obj) {

			var coord = self._geoCoord[obj.name];
			var pos = self.geoCoord2Pixel(coord);
			obj.x = pos[0]; //- self._mapOffset[0];
			obj.y = pos[1]; //- self._mapOffset[1];
		};

		/**
		 * 绑定地图事件的处理方法
		 *
		 * @private
		 */
		self._bindEvent = function () {
			self._map.on('resize', function(){
				//lamb 20160718 添加容器resize事件
				var mapsize = self._map.getSize();
				self._echartsContainer.style.width = mapsize.x + 'px';
				self._echartsContainer.style.height = mapsize.y + 'px';
				if (self._ec) self._ec.resize();
			});
			//self._map.on('movestart', _moveHandler('movestart'));
			self._map.on('move', _moveHandler('moving'));
			//self._map.on('moveend', _moveHandler('moveend'));
			self._map.on('zoomstart', function () {
				//self.clear();
			}); //去掉zoomstart事件
			self._map.on('zoomend', _zoomChangeHandler);
			/*
			self._ec.getZrender().on('dragstart', _dragZrenderHandler(true));
			self._ec.getZrender().on('dragend', _dragZrenderHandler(false));
			self._ec.getZrender().on('mouseup', function() {
			// self.setOption(self._option);
			//修改了echarts源码解决了这个问题
			});
			self._ec.getZrender().on('mousedown', function() {
			// if (self._ec)  self._ec.clear();
			//修改了echarts源码解决了这个问题
			});*/
			self._ec.getZrender().on('mousewheel', function (e) {
				var map = self._map,
				zoom = map.getZoom();
				var delta = L.DomEvent.getWheelDelta(e.event);
				if(zoom >= map.getMaxZoom() && delta > 0) return;
				if(zoom <= map.getMinZoom() && delta < 0) return;
				self.clear(); //在mousewheel的时候清除echarts内容
				/*
				self._lastMousePos = self._map.mouseEventToContainerPoint(e.event);
				var delta = L.DomEvent.getWheelDelta(e.event);
				var map = self._map,
				zoom = map.getZoom();
				delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta);
				delta = Math.max(Math.min(delta, 4), -4);
				delta = map._limitZoom(zoom + delta) - zoom;

				self._delta = 0;
				self._startTime = null;

				if (!delta) {
					return;
				}

				if (map.options.scrollWheelZoom === 'center') {
					map.setZoom(zoom + delta);
				} else {
					map.setZoomAround(self._lastMousePos, zoom + delta);
				}
				*/
			});
		};
		/*
		self._unbindEvent = function () {
			self._map.off('move', _moveHandler('moving'));
			self._map.off('moveend', _moveHandler('moveend'));
			self._map.off('zoomstart', function () {
				if (self._ec)  self._ec.clear();
			}); //去掉zoomstart事件
			self._map.off('zoomend', _zoomChangeHandler);
			self._ec.getZrender().un('mousewheel', function (e) {
				if (self._ec)  self._ec.clear(); //在mousewheel的时候清除echarts内容
				self._lastMousePos = self._map.mouseEventToContainerPoint(e.event);
				var delta = L.DomEvent.getWheelDelta(e.event);
				var map = self._map,
				zoom = map.getZoom();
				delta = delta > 0 ? Math.ceil(delta) : Math.floor(delta);
				delta = Math.max(Math.min(delta, 4), -4);
				delta = map._limitZoom(zoom + delta) - zoom;

				self._delta = 0;
				self._startTime = null;

				if (!delta) {
					return;
				}

				if (map.options.scrollWheelZoom === 'center') {
					map.setZoom(zoom + delta);
				} else {
					map.setZoomAround(self._lastMousePos, zoom + delta);
				}
			});
		};
*/
		/**
		 * 地图缩放触发事件
		 *
		 * @private
		 */
		function _zoomChangeHandler() {
			self.setOption(self._option);
		}

		// function _zoomatartChangeHandler() {
		//   if (self._ec)  self._ec.clear();
		// }

		/**
		 * 地图移动、如拖拽触发事件
		 *
		 * @param {string} type moving | moveend  移动中|移动结束
		 * @return {Function}
		 * @private
		 */
		function _moveHandler(type) {
			return function () {
				/*
				var domPosition = self._map._getMapPanePos();
				// 记录偏移量
				self._mapOffset = [-parseInt(domPosition.x) || 0, -parseInt(domPosition.y) || 0];
				self._echartsContainer.style.left = self._mapOffset[0] + 'px';
				self._echartsContainer.style.top = self._mapOffset[1] + 'px';
				*/
				if (self._ec) self.setOption(self._option);
				//_fireEvent(type);
				if (type == 'movestart') {
					//self.clear();
				}
				if (type == 'moveend') {
					if (self._ec) self.setOption(self._option);
				}
			}
		}

		/**
		 * Zrender拖拽触发事件
		 *
		 * @param {boolean} isStart
		 * @return {Function}
		 * @private
		 */
		function _dragZrenderHandler(isStart) {

			return function () {
				var func = isStart ? 'disable' : 'enable';
				if (isStart) {
					self.clear();
				} else {
					if (self._ec) self.setOption(self._option);
				}
				self._map.dragging[func]();
			};
		}
	};
	return LeafletMapExt;
});
